前言

在分布式系统中,由于服务众多的关系,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件,而 Spring Cloud Config 项目就是一个能解决分布式系统需求的配置管理方案。

Spring Cloud Config 分为 server 和 client 两个部分: server 用于从 GitHub 或其他地方获取配置文件、存储,并通过 HTTP 接口的方式将它们提供给 client , client 再通过这些配置文件来初始化自身。

按照官方文档的说明,想要获取官方示例中的 https://github.com/spring-cloud-samples/config-repo/blob/master/test.json 文件,在配置好 server 之后, client 就可以访问 server 的 /{name}/{profile}/{label}/{path} (这里是 /foo/default/master/test.json ) HTTP 接口, server 会访问 GitHub 并将文件下载到本地,然后通过 HTTP 响应返回给 client 。

在这个过程中,由于 server 没有对输入的 path 进行检查的原因,所以存在一个服务端目录穿越和任意文件读取的漏洞。


环境搭建

嫌麻烦的我直接在本机上面跑了,用 maven 新建一个 spring-boot 的项目,配置文件如下:

pom.xml:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.6.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
        <version>1.4.0.RELEASE</version>
    </dependency>
</dependencies>

application.yml:

server:
  port: 80
  context-path: /spring-boot-quick-start
logging:
  level:
    root: INFO
    org:
      springframework:
        web: DEBUG
        security: DEBUG
spring:
  jpa:
    show-sql: true
  messages:
    basename: i18n/messages, i18n/messages_zh
  cloud:
    config:
      server:
        default-application-name: config-server
        git:
          uri: https://github.com/spring-cloud-samples/config-repo.git
      label: master

management:
  security:
    roles: ADMIN

Application.java:

package Twings;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(Application.class);
    }

    public static void main(String args[]) {
        SpringApplication.run(Application.class, args);
    }

}

想要使用其他版本组件的也可以自行更改,版本可以在 maven 的仓库上查找: https://mvnrepository.com/

特别方便,不过要注意下兼容的问题。

开启 Web 服务,然后访问 test.json :


漏洞复现与分析

在C盘根目录放置一个twings.txt,payload:

http://localhost/spring-boot-quick-start/foo/default/master/..%252F..%252F..%252F..%252F..%252F..%252Ftwings.txt

找到 /{name}/{profile}/{label}/{path} 路由并下断点开启调试:

因为过程很简单,调用链也不长,所以我就从简了,直接来到 findOne 函数:

这里通过相对路径的方式打开了文件,然后调用 openConnection 打开了 file 协议的 url 的连接并在 Handler类中调用 ParseUtil.decode 进行了 URL 解码得到了可以进行目录穿越的payload:

最后调用了StreamUtils.copyToString(is, Charset.forName(“UTF-8”)),将文件内容读入了字符串中进行返回:

成功穿越目录读取了文件。


参考文章:

https://xz.aliyun.com/t/2479

https://cloud.spring.io/spring-cloud-static/spring-cloud.html#_serving_plain_text

https://www.cnblogs.com/shamo89/p/8016908.html

https://www.cnblogs.com/cralor/p/9239976.html

https://www.cnblogs.com/huangjuncong/p/9069749.html

https://www.jianshu.com/p/794fe4761b1f


Web Java 复现 Spring

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

DDCTF2019-Web题解
Nodejs/express/session-file-store库下的session伪造